package uqbar.comm.netty;

import java.net.SocketAddress;
import java.nio.charset.Charset;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.oio.SerialChannelFactory;
import org.jboss.netty.channel.socket.oio.SerialPortSocketAddress;

public class Client {

	private Channel channel;
	SocketAddress port = new SerialPortSocketAddress("/dev/ttyACM0");
	private ChannelPipelineFactory pipelineFactory;

	public Client(final ChannelHandler channelHandler) {
		this(new ChannelPipelineFactory() {

			public ChannelPipeline getPipeline() throws Exception {
				return Channels.pipeline(channelHandler);
			}
		});
	}

	public Client(final ChannelPipelineFactory pipelineFactory) {
		this.pipelineFactory = pipelineFactory;

	}

	public void init() {

		// ChannelFactory channelFactory = new
		// SerialChannelFactory(Executors.newSingleThreadExecutor());
		ChannelFactory channelFactory = new SerialChannelFactory(Executors.newSingleThreadExecutor());

		ClientBootstrap clientBootstrap = new ClientBootstrap(channelFactory);
		clientBootstrap.setPipelineFactory(this.pipelineFactory);
		ChannelFuture connect = clientBootstrap.connect(this.port);
		this.channel = connect.awaitUninterruptibly().getChannel();
	}

	public ChannelFuture write(final String output) {
		if (!this.channel.isConnected()) {
			this.reconnect();
		}
		return this.channel.write(ChannelBuffers.copiedBuffer(output, Charset.defaultCharset()));
	}

	public ChannelFuture write(final Object output) {
		if (!this.channel.isConnected()) {
			this.reconnect();
		}
		return this.channel.write(output);
	}

	protected void reconnect() {
		ChannelFuture connect = this.channel.connect(this.port);
		this.channel = connect.awaitUninterruptibly().getChannel();
	}

	public void close() {
		this.channel.close();
	}
}
